package info.empathymobile.batterymonitorapp;

import flexjson.JSONDeserializer;
import flexjson.JSONSerializer;
import info.empathymobile.monitor.business.beans.MonitorEntry;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;

public class ServerSyncBO {
	public static final String EMPATHY_SERVER_URL = "http://empathymobile.info/server";
	public static final String EMPATHY_MONITOR_SYNC_PATH = "/empathy_monitor_sync";
	public static final String AUTH_KEY_PARAM = "auth_key";
	public static final String USER_UUID_PARAM = "user_uuid";
	public static final String MONITOR_ENTRIES_PARAM = "monitor_entries";
	
	public final static String EMPATHY_USER_UUID_PREF = "EmpathyUserUUID";
	
	public String getUserUUID(Context context){
		SharedPreferences sharedPref = context.getSharedPreferences(MainActivity.EMPATHY_SURVEY_SHARED_PREFERENCES, Context.MODE_MULTI_PROCESS);
		
		String userUUID = sharedPref.getString(EMPATHY_USER_UUID_PREF, null);
		
		if(userUUID == null){
			TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
			userUUID = telephonyManager.getDeviceId(); //First attemp
			
			if (userUUID == null) {
				userUUID = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); //Second attemp
				if(userUUID == null) {
					userUUID = telephonyManager.getSubscriberId(); //Third attemp
					if(userUUID == null){
						try {     
							Class<?> c = Class.forName("android.os.SystemProperties");        	 
							Method get = c.getMethod("get", String.class, String.class );                     
							userUUID = (String)(   get.invoke(c, "ro.serialno", (Object[]) null )  ); //Last attemp           
						}                                                                                 
						catch (Exception ignored)                                                         
						{ 
						}
						if(userUUID == null){ //Them...generate a UUID
							userUUID = UUID.randomUUID().toString();
						}
					}
				}
			} 
			
			SharedPreferences.Editor sharedPrefEditor = sharedPref.edit();
			sharedPrefEditor.putString(EMPATHY_USER_UUID_PREF, userUUID);
			sharedPrefEditor.commit();
		}
		
		return userUUID;
	}
	
	public ArrayList<Integer> syncWithEmpathyServer(List<MonitorEntry> entries, String userUUID, String auth_key) throws IOException, JSONException{
		HttpPost httpPost = new HttpPost(EMPATHY_SERVER_URL + EMPATHY_MONITOR_SYNC_PATH);
		httpPost.setHeader("Content-Type","application/json");
		httpPost.setHeader("Accept", "application/json");

		httpPost.setEntity(new StringEntity(buildJsonMessage(entries, userUUID, auth_key), "UTF-8"));
        
		return parseHttpResponse(new DefaultHttpClient().execute(httpPost));
	}

	private String buildJsonMessage(List<MonitorEntry> entries, String userUUID, String auth_key) throws JSONException {
		JSONSerializer serializer = new JSONSerializer(); 
	    String jsonEntries = serializer.exclude("*.class").serialize(entries);
	    
		JSONObject jsonObj = new JSONObject();
		jsonObj.put(MONITOR_ENTRIES_PARAM, new JSONArray(jsonEntries));
		jsonObj.put(AUTH_KEY_PARAM, auth_key);
		jsonObj.put(USER_UUID_PARAM, userUUID);
		return jsonObj.toString();
	}

	private ArrayList<Integer> parseHttpResponse(HttpResponse response) throws IOException {
		String result = null;
		HttpEntity entity = response.getEntity();
		if (entity != null) {
		    InputStream instream = entity.getContent();
		    result = convertStreamToString(instream);
		    instream.close();
		}
		
		ArrayList<Integer> successfulSyncIds = new ArrayList<Integer>();
	    if(result != null){
		    JSONDeserializer<ArrayList<Integer>> deserializer = new JSONDeserializer<ArrayList<Integer>>();
			try {
				successfulSyncIds = deserializer.deserialize(result);
			} catch (Exception e) {
				//Do nothing when a class cast exception occur on deserialization because its a non serializable http result
			}
	    }
		return successfulSyncIds;
	}
	
	public String convertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}
